package com.googlecode.bip.dao.mysql;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.SQLException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import org.apache.log4j.Logger;
import com.googlecode.bip.dao.DAOFactory;
import com.googlecode.bip.dao.LocalDAO;
import com.googlecode.bip.dao.QuestionDAO;
import com.googlecode.bip.dao.ReferentDAO;
import com.googlecode.bip.dao.ReferentReferentViewDAO;
import com.googlecode.bip.dao.TopicDAO;
import com.googlecode.bip.dao.UserDAO;
import com.googlecode.bip.dao.UserIgnoreQuestionDAO;
import com.googlecode.bip.dao.UserReferentDAO;
import com.googlecode.bip.dao.UserValueDAO;

/**
 * DAOFactory for MySQL
 *
 * @author Claude CHOISNET
 */
public class MySQLDAOFactory
    extends DAOFactory
        implements Serializable
{
    private static final long serialVersionUID = 1L;
    private static transient DataSource dataSource;

    /**
     * Create DAOFactory for MySQL
     */
    public MySQLDAOFactory()
    {
    }

    /**
     * Returns DataSource
     * @return DataSource
     * @throws NamingException
     */
    private static DataSource createDataSource()
        throws NamingException
    {
        if( dataSource == null ) {
            final Context ctx = new InitialContext();

            dataSource = DataSource.class.cast(
                    ctx.lookup("java:comp/env/jdbc/bipol")
                    );
            }
        return dataSource;
    }

    /**
     * Create a new {@link Connection} if not already initialized
     * <br>
     * Method to create MySQL connections
     *
     * @return a new Connection
     * @throws NamingException
     * @throws SQLException
     */
    private static Connection createConnection()
        throws NamingException, SQLException
    {
        DataSource  ds      = createDataSource();
        Connection  conn    = null;
        int         count   = 0;

        do {
            conn = ds.getConnection();

            if( conn.isClosed() && ++count > 10 ) {
                throw new SQLException("can't getConnection() - connection is closed");
                }
            } while( conn == null || conn.isClosed() );

        return conn;
    }

    /**
     * Returns a new Connection build from DataSource, this Connection
     * must be close !
     * @return a Connection build from DataSource
     * @throws SQLException if any
     * @throws NamingException if any
     */
    public static Connection getConnection() // static ??
        throws NamingException, SQLException
    {
        return createConnection();
    }

    /**
     * TODO: Doc!
     *
     * @param connection
     * @throws IllegalArgumentException
     * @throws SQLException
     */

    public static void returnConnectionToPool( Connection connection )
        throws IllegalArgumentException, SQLException // static ??
    {
        try {
            connection.close();
            }
        catch( Exception e ) {
            Logger.getLogger( MySQLDAOFactory.class ).warn(
                    "Exception while closing DB connection",
                    e
                    );
            }
    }

    @Override
    public LocalDAO getLocalDAO()
    {
        return new MySQLLocalDAO();
    }

    @Override
    public TopicDAO getTopicDAO()
    {
        return new MySQLTopicDAO();
    }

    @Override
    public QuestionDAO getQuestionDAO()
    {
        return new MySQLQuestionDAO();
    }

    @Override
    public UserDAO getUserDAO()
    {
        return new MySQLUserDAO();
    }

    @Override
    public UserValueDAO getUserValueDAO()
    {
        return new MySQLUserValueDAO();
    }

    @Override
    public UserIgnoreQuestionDAO getUserIgnoreQuestionDAO()
    {
        return new MySQLUserIgnoreQuestionDAO();
    }

    @Override
    public ReferentDAO getReferentDAO()
    {
        return new MySQLReferentDAO();
    }

    @Override
    public ReferentReferentViewDAO getReferentReferentViewDAO()
    {
        return new MySQLReferentReferentViewDAO();
    }

    @Override
    public UserReferentDAO getUserReferentDAO()
    {
        return new MySQLUserReferentDAO();
    }



}

